package com.tao.mytestdd.datagrama

import java.io.ByteArrayInputStream
import java.io.ObjectInputStream
import java.net.DatagramPacket

/**
 *reate by tao on{DATE}
 * udp 数据处理单元
 */
class UDPDatagramOperate {
    var useSession = false
    private val seccionMap = HashMap<String, SeccionInfo>()
    private val packageMap = HashMap<Int, ArrayList<DataEntity<String?>>>()

    fun putSession(config: SeccionInfo) {
        synchronized(seccionMap) {
            seccionMap.put(config.session, config)
        }
    }

    fun removeSession(session: String) {
        synchronized(seccionMap) {
            seccionMap.remove(session)
        }
    }

    fun receiverMsg(packet: DatagramPacket): DataEntity<String?>? {

        System.err.println("UDP receiverMsg:" + packet.length)
        val dataBuff = ByteArray(packet.length)
        System.arraycopy(packet.data, 0, dataBuff, packet.offset, dataBuff.size)
        try {
            val entity = ObjectInputStream(ByteArrayInputStream(dataBuff)).readObject() as DataEntity<String?>

            if (useSession && !checkSession(entity)) {
                return null
            }
            packageMap.get(entity.packageTag)?.let {
                it.add(entity)
            } ?: let {
                packageMap.put(entity.packageTag, arrayListOf())
                packageMap.get(entity.packageTag)?.add(entity)
            }
            packageMap.get(entity.packageTag)?.let { list ->

                val iterator = list.iterator()

                while (iterator.hasNext()) {
                    val next = iterator.next()
                    if (next.pckageCount != list.size) {
                        if (System.currentTimeMillis() - next.timeStamp > next.packageVaildTime) {
                            iterator.remove()
                        }
                    } else {
                        list.sortBy { it.index }
                        var buff = ByteArray(0)
                        list.forEach {
                            System.err.println("lenth:" + it.objBytes.size)
                            val bf = ByteArray(buff.size + it.objBytes.size)
                            System.arraycopy(buff, 0, bf, 0, buff.size)
                            System.arraycopy(it.objBytes, 0, bf, buff.size, it.objBytes.size)
                            buff = bf
                        }
                        entity.objBytes = buff
                        entity.obj = String(buff)
                        packageMap.remove(entity.packageTag)
                        return entity
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            clear()
        }

        return null
    }

    private fun checkSession(entity: DataEntity<String?>): Boolean {
        synchronized(seccionMap) {
            val iterator = seccionMap.iterator()

            while (iterator.hasNext()) {
                val next = iterator.next()
                val key = next.key
                val value = next.value

                if (System.currentTimeMillis() - value.timeStamp > value.vaildTime) {
                    iterator.remove()
                    continue
                }
                if (entity.session == key) {
                    return true
                }
            }
            return false
        }
    }

    fun clear() {
        val iterator = packageMap.iterator()

        while (iterator.hasNext()) {
            val next = iterator.next()
            val key = next.key
            val value = next.value
            val listIter = value.iterator()
            while (listIter.hasNext()) {
                val next = listIter.next()
                if (next.pckageCount != value.size) {
                    if (System.currentTimeMillis() - next.timeStamp > next.packageVaildTime) {
                        listIter.remove()
                    }
                }
            }
            if (value.isNullOrEmpty()) {
                packageMap.remove(key)
            }

        }

    }

}